/* eslint-disable no-unused-vars */
import namespace from "../../namespace";

const Canvas = namespace.Canvas;

/**
 * 框选交互
 */
class SelectionPolicy extends namespace.policy.canvas.DragDropPolicy {
  NAME = "namespace.policy.SelectionPolicy";

  constructor() {
    super();

    this.isInsideMode = (rect1, rect2) => rect1.isInside(rect2);

    this.isDrag = false;

    this.boxFigureOuter = null;
    this.boxFigureInner = null;
    this.mouseDownElement = null;
    this.canDrawBox = false;

    this.x = 0;
    this.y = 0;
  }

  onMouseDown(canvas, x, y) {
    this.x = x;
    this.y = y;
    this.canDrawBox = true;

    this.isDrag = true;

    let figure = canvas.getBestFigure(x, y);

    let selection = canvas.getSelection();
    let figures = selection.getAll();

    let isContains = selection.contains(figure);

    if (figure && figure.isSelectable() && !isContains) {
      figures.each((i, f) => f.unselect(canvas));
    }

    // 选中图形
    if (figure && figure.isDraggable()) {
      figure.onDragStart(x, y);
      this.canDrawBox = false;
      figures.each((i, f) =>
        f.onDragStart(x - figure.getAbsoluteX(), y - figure.getAbsoluteY())
      );
    }

    // 图形可以被框选中
    if (figure && figure.isSelectable()) {
      figure.select(canvas);
    }

    this.mouseDownElement = figure;
  }

  onMouseDrag(canvas, dx, dy, dx2, dy2, event) {
    // 拖动元素 如果存在 mouseDownElement
    super.onMouseDrag(canvas, dx, dy, dx2, dy2, event);

    if (!this.canDrawBox) {
      return;
    }

    if (this.boxFigureInner === null) {
      this.boxFigureInner = new namespace.shape.Rectangle({
        width: 1,
        height: 1,
        x: this.x,
        y: this.y,
        bgColor: "#d4d1d4",
        alpha: 0.1
      });

      this.boxFigureOuter = new namespace.shape.Rectangle({
        width: 1,
        height: 1,
        x: this.x,
        y: this.y,
        dash: "--",
        stroke: 0.5,
        bgColor: null
      });

      this.boxFigureOuter.setCanvas(canvas);
      this.boxFigureInner.setCanvas(canvas);
    }
    let abs = Math.abs;
    if (this.boxFigureInner !== null) {
      this.boxFigureOuter.setDimension(abs(dx), abs(dy));
      this.boxFigureOuter.setPosition(
        this.x + Math.min(0, dx),
        this.y + Math.min(0, dy)
      );
      this.boxFigureInner.setDimension(abs(dx), abs(dy));
      this.boxFigureInner.setPosition(
        this.x + Math.min(0, dx),
        this.y + Math.min(0, dy)
      );
    }
  }

  onMouseUp(canvas, x, y) {
    let all = canvas.getSelection().getAll();

    if (this.mouseDownElement === null) {
      all.each((i, figure) => this.unselect(figure));
    }

    if (this.mouseDownElement) {
      all.each((i, f) => f.onDragEnd(x, y));
    }

    // 进行框选
    if (this.boxFigureInner !== null) {
      let selectionRect = this.boxFigureOuter.getBoundingBox();
      // 检测碰撞图形
      canvas.figures.each((i, figure) => {
        if (
          figure.isSelectable() &&
          this.isInsideMode(figure.getBoundingBox(), selectionRect)
        ) {
          figure.select(canvas, figure);
        }
      });

      this.boxFigureOuter.setCanvas(null);
      this.boxFigureInner.setCanvas(null);
      this.boxFigureOuter = null;
      this.boxFigureInner = null;
    }

    this.canDrawBox = false;
    this.isDrag = false;
    this.mouseDownElement = null;

    // 获取最新的框选图形信息
    all = canvas.getSelection().getAll();

    // 框选/未框选 事件
    this.canvas.emit(
      all.getSize()
        ? Canvas.EVENTS.FIGURE_SELECTION
        : Canvas.EVENTS.FIGURE_UNSELECTION,
      all
    );
  }

  unselect(figure) {
    this.canvas.getSelection().remove(figure);
    figure.unselect(this.canvas);
  }
}

namespace.policy.canvas.SelectionPolicy = SelectionPolicy;
